/*
 * Copyright (C) 2014 Moncef YABI
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.joge.core.input;

import java.util.Arrays;

import org.lwjgl.input.Keyboard;

/**
 * Klasse JKeyboard behandelt alle an sie gesendete Tastaure-Events
 *
 * @author Moncef YABI
 */
public class JKeyboard
{

    public static final int ANY_CONTROLLER = -1;
    public static final int KEY_ESCAPE = 0x01;
    public static final int KEY_1 = 0x02;
    public static final int KEY_2 = 0x03;
    public static final int KEY_3 = 0x04;
    public static final int KEY_4 = 0x05;
    public static final int KEY_5 = 0x06;
    public static final int KEY_6 = 0x07;
    public static final int KEY_7 = 0x08;
    public static final int KEY_8 = 0x09;
    public static final int KEY_9 = 0x0A;
    public static final int KEY_0 = 0x0B;
    public static final int KEY_MINUS = 0x0C; /* - on main keyboard */

    public static final int KEY_EQUALS = 0x0D;
    public static final int KEY_BACK = 0x0E; /* backspace */

    public static final int KEY_TAB = 0x0F;
    public static final int KEY_Q = 0x10;
    public static final int KEY_W = 0x11;
    public static final int KEY_E = 0x12;
    public static final int KEY_R = 0x13;
    public static final int KEY_T = 0x14;
    public static final int KEY_Y = 0x15;
    public static final int KEY_U = 0x16;
    public static final int KEY_I = 0x17;
    public static final int KEY_O = 0x18;
    public static final int KEY_P = 0x19;
    public static final int KEY_LBRACKET = 0x1A;
    public static final int KEY_RBRACKET = 0x1B;
    public static final int KEY_RETURN = 0x1C; /* Enter on main keyboard */

    public static final int KEY_ENTER = 0x1C; /* Enter on main keyboard */

    public static final int KEY_LCONTROL = 0x1D;
    public static final int KEY_A = 0x1E;
    public static final int KEY_S = 0x1F;
    public static final int KEY_D = 0x20;
    public static final int KEY_F = 0x21;
    public static final int KEY_G = 0x22;
    public static final int KEY_H = 0x23;
    public static final int KEY_J = 0x24;
    public static final int KEY_K = 0x25;
    public static final int KEY_L = 0x26;
    public static final int KEY_SEMICOLON = 0x27;
    public static final int KEY_APOSTROPHE = 0x28;
    public static final int KEY_GRAVE = 0x29; /* accent grave */

    public static final int KEY_LSHIFT = 0x2A;
    public static final int KEY_BACKSLASH = 0x2B;
    public static final int KEY_Z = 0x2C;
    public static final int KEY_X = 0x2D;
    public static final int KEY_C = 0x2E;
    public static final int KEY_V = 0x2F;
    public static final int KEY_B = 0x30;
    public static final int KEY_N = 0x31;
    public static final int KEY_M = 0x32;
    public static final int KEY_COMMA = 0x33;
    public static final int KEY_PERIOD = 0x34; /* . on main keyboard */

    public static final int KEY_SLASH = 0x35; /* / on main keyboard */

    public static final int KEY_RSHIFT = 0x36;
    public static final int KEY_MULTIPLY = 0x37; /* * on numeric keypad */

    public static final int KEY_LMENU = 0x38; /* left Alt */

    public static final int KEY_SPACE = 0x39;
    public static final int KEY_CAPITAL = 0x3A;
    public static final int KEY_F1 = 0x3B;
    public static final int KEY_F2 = 0x3C;
    public static final int KEY_F3 = 0x3D;
    public static final int KEY_F4 = 0x3E;
    public static final int KEY_F5 = 0x3F;
    public static final int KEY_F6 = 0x40;
    public static final int KEY_F7 = 0x41;
    public static final int KEY_F8 = 0x42;
    public static final int KEY_F9 = 0x43;
    public static final int KEY_F10 = 0x44;
    public static final int KEY_NUMLOCK = 0x45;
    public static final int KEY_SCROLL = 0x46; /* Scroll Lock */

    public static final int KEY_NUMPAD7 = 0x47;
    public static final int KEY_NUMPAD8 = 0x48;
    public static final int KEY_NUMPAD9 = 0x49;
    public static final int KEY_SUBTRACT = 0x4A; /* - on numeric keypad */

    public static final int KEY_NUMPAD4 = 0x4B;
    public static final int KEY_NUMPAD5 = 0x4C;
    public static final int KEY_NUMPAD6 = 0x4D;
    public static final int KEY_ADD = 0x4E; /* + on numeric keypad */

    public static final int KEY_NUMPAD1 = 0x4F;
    public static final int KEY_NUMPAD2 = 0x50;
    public static final int KEY_NUMPAD3 = 0x51;
    public static final int KEY_NUMPAD0 = 0x52;
    public static final int KEY_DECIMAL = 0x53; /* . on numeric keypad */

    public static final int KEY_F11 = 0x57;
    public static final int KEY_F12 = 0x58;
    public static final int KEY_F13 = 0x64; /* (NEC PC98) */

    public static final int KEY_F14 = 0x65; /* (NEC PC98) */

    public static final int KEY_F15 = 0x66; /* (NEC PC98) */

    public static final int KEY_KANA = 0x70; /* (Japanese keyboard) */

    public static final int KEY_CONVERT = 0x79; /* (Japanese keyboard) */

    public static final int KEY_NOCONVERT = 0x7B; /* (Japanese keyboard) */

    public static final int KEY_YEN = 0x7D; /* (Japanese keyboard) */

    public static final int KEY_NUMPADEQUALS = 0x8D; /*
     * = on numeric keypad
     * (NEC PC98)
     */

    public static final int KEY_CIRCUMFLEX = 0x90; /* (Japanese keyboard) */

    public static final int KEY_AT = 0x91; /* (NEC PC98) */

    public static final int KEY_COLON = 0x92; /* (NEC PC98) */

    public static final int KEY_UNDERLINE = 0x93; /* (NEC PC98) */

    public static final int KEY_KANJI = 0x94; /* (Japanese keyboard) */

    public static final int KEY_STOP = 0x95; /* (NEC PC98) */

    public static final int KEY_AX = 0x96; /* (Japan AX) */

    public static final int KEY_UNLABELED = 0x97; /* (J3100) */

    public static final int KEY_NUMPADENTER = 0x9C; /* Enter on numeric keypad */

    public static final int KEY_RCONTROL = 0x9D;
    public static final int KEY_NUMPADCOMMA = 0xB3; /*
     * , on numeric keypad (NEC
     * PC98)
     */

    public static final int KEY_DIVIDE = 0xB5; /* / on numeric keypad */

    public static final int KEY_SYSRQ = 0xB7;
    public static final int KEY_RMENU = 0xB8; /* right Alt */

    public static final int KEY_PAUSE = 0xC5; /* Pause */

    public static final int KEY_HOME = 0xC7; /* Home on arrow keypad */

    public static final int KEY_UP = 0xC8; /* UpArrow on arrow keypad */

    public static final int KEY_PRIOR = 0xC9; /* PgUp on arrow keypad */

    public static final int KEY_LEFT = 0xCB; /* LeftArrow on arrow keypad */

    public static final int KEY_RIGHT = 0xCD; /* RightArrow on arrow keypad */

    public static final int KEY_END = 0xCF; /* End on arrow keypad */

    public static final int KEY_DOWN = 0xD0; /* DownArrow on arrow keypad */

    public static final int KEY_NEXT = 0xD1; /* PgDn on arrow keypad */

    public static final int KEY_INSERT = 0xD2; /* Insert on arrow keypad */

    public static final int KEY_DELETE = 0xD3; /* Delete on arrow keypad */

    public static final int KEY_LWIN = 0xDB; /* Left Windows key */

    public static final int KEY_RWIN = 0xDC; /* Right Windows key */

    public static final int KEY_APPS = 0xDD; /* AppMenu key */

    public static final int KEY_POWER = 0xDE;
    public static final int KEY_SLEEP = 0xDF;
    public static final int KEY_LALT = KEY_LMENU;
    public static final int KEY_RALT = KEY_RMENU;
    private static final char[] keyBoradKeys = new char[1024];
    private static final boolean[] keyPressed = new boolean[1024];
    private static final long[] nextKeyRepeat = new long[1024];
    private static final long delay = 200;



    public static void fireKeyboard()
    {
        while (Keyboard.next())
        {
            if (Keyboard.getEventKeyState())
            {
                keyBoradKeys[Keyboard.getEventKey()] = Keyboard
                        .getEventCharacter();
                keyPressed[Keyboard.getEventKey()] = true;
                nextKeyRepeat[Keyboard.getEventKey()] = System
                        .currentTimeMillis()
                        + getDelay();
                JHID.getjHID().fireKeyPressedEvent(Keyboard.getEventKey(), Keyboard.getEventCharacter());
            } else
            {
                nextKeyRepeat[Keyboard.getEventKey()] = 0;
                JHID.getjHID().firekeyReleased(Keyboard.getEventKey(), keyBoradKeys[Keyboard.getEventKey()]);
            }
        }
        for (int i = 0; i < 1024; i++)
        {
            if (keyPressed[i] && (nextKeyRepeat[i] != 0) && System.currentTimeMillis() > nextKeyRepeat[i])
            {
                if (System.currentTimeMillis() > nextKeyRepeat[i])
                {
                    nextKeyRepeat[i] = System.currentTimeMillis() + getDelay();
                    JHID.getjHID().firekeyLongPressed(i, keyBoradKeys[i]);
                }
            }
        }
    }

    /**
     * @param keyIndex of key
     *
     * @return KeyName
     */
    public static String getKeyName(int keyIndex)
    {
        return Keyboard.getKeyName(keyIndex);
    }

    /**
     * Rausfinden ob eine Taste gedruckt ist
     */
    public static boolean isKeyPressed(int index)
    {
        if (keyPressed[index])
        {
            keyPressed[index] = false;
            return true;
        }

        return false;
    }

    /**
     * loesche alle in keyPressed geschpeicherte Daten
     */
    public static void clearKeyPressed()
    {
        Arrays.fill(keyPressed, false);
    }

    /**
     * @param index
     * @return key
     */
    public static boolean isKeyDown(int index)
    {
        return Keyboard.isKeyDown(index);
    }

    private static long getDelay()
    {
        return delay;
    }
}
